using System;
using System.Collections.Generic;
using Weather.com.Client.WeatherConditions.Common;
using Weather.com.Client.WeatherConditions.CurrentConditions;
using Weather.com.Client.WeatherConditions.Forecasts;
using Weather.com.Client.WeatherConditions.Location;

namespace Weather.com.Client
{
    /// <summary>
    /// Interface of the Client for the weather.com service
    /// </summary>
    public interface IWeatherClient
    {
        /// <summary>
        /// Sets/gets Timeout value for WeatherClient when querying Weather.com service
        /// </summary>
        TimeSpan Timeout { get; set; }

        /// <summary>
        /// When set to true Promotion links collection is populate and should be diplayed 
        /// together with the weather conditions information
        /// </summary>
        bool IncludePromotionLink { get; set; }

        /// <summary>
        /// Allows to get and set Metric or Standard metric systems for the weather conditions data being retrieved.
        /// </summary>
        UnitsSystem Units { get; set; }

        /// <summary>
        /// Retrieves location data in the XML format 
        /// </summary>
        /// <param name="locationName">location name</param>
        /// <returns>Location search data in the XML format</returns>
        string GetLocationAsXml(string locationName);

        /// <summary>
        /// Performs location search for provided location name. 
        /// </summary>
        /// <param name="locationName">location name, for the non-US countries should be "Country,City". For US-based cities only city name is required.</param>
        /// <returns>List of locations, or empty collection is nothing has been found</returns>
        List<Location> GetLocation(string locationName);

        /// <summary>
        /// Begins an asynchronous location search operation.
        /// </summary>
        /// <param name="locationName">location name, for the non-US countries should be "Country,City". For US-based cities only city name is required.</param>
        /// <param name="userCallback">An optional asynchronous callback, to be called when the location search is complete.</param>
        /// <param name="stateObject">A user-provided object that distinguishes this particular asynchronous location search request from other requests.</param>
        /// <returns>An IAsyncResult that represents the asynchronous location search, which could still be pending.</returns>
        IAsyncResult BeginGetLocation(string locationName, AsyncCallback userCallback, Object stateObject);

        /// <summary>
        /// Waits for the pending asynchronous location search to complete.
        /// </summary>
        /// <param name="result">The reference to the pending asynchronous request to finish.</param>
        /// <returns>List of locations, or empty collection is nothing has been found</returns>
        List<Location> EndGetLocation(IAsyncResult result);

        /// <summary>
        /// Retrieves todays weather for given location. 
        /// </summary>
        /// <param name="location">location</param>
        /// <returns>Current conditions data in the XML format</returns>
        string GetCurrentConditionsAsXml(Location location);

        /// <summary>
        /// Retrives todays weather for given location. 
        /// </summary>
        /// <param name="location">location</param>
        /// <returns>Current weather conditions</returns>
        CurrentWeatherInfo GetCurrentConditions(Location location);

        /// <summary>
        /// Retrives todays weather for given US Zip Code
        /// </summary>
        /// <param name="zipCode">US 5-digit zip code</param>
        /// <returns>Current weather conditions</returns>
        CurrentWeatherInfo GetCurrentConditions(USZipCode zipCode);

        /// <summary>
        /// Begins an asynchronous todays weather conditions retrieval operation for a given location. 
        /// </summary>
        /// <param name="location">location</param>
        /// <param name="userCallback">An optional asynchronous callback, to be called when the todays weather condition retrieval is complete.</param>
        /// <param name="stateObject">A user-provided object that distinguishes this particular asynchronous todays weather condition retrieval request from other requests.</param>
        /// <returns>An IAsyncResult that represents the asynchronous todays weather condition retrieval, which could still be pending.</returns>
        IAsyncResult BeginGetCurrentConditions(Location location, AsyncCallback userCallback, Object stateObject);

        /// <summary>
        /// Begins an asynchronous todays weather conditions retrieval operation for a given US Zip Code . 
        /// </summary>
        /// <param name="zipCode">US 5-digit zip code</param>
        /// <param name="userCallback">An optional asynchronous callback, to be called when the todays weather condition retrieval is complete.</param>
        /// <param name="stateObject">A user-provided object that distinguishes this particular asynchronous todays weather condition retrieval request from other requests.</param>
        /// <returns>An IAsyncResult that represents the asynchronous todays weather condition retrieval, which could still be pending.</returns>
        IAsyncResult BeginGetCurrentConditions(USZipCode zipCode, AsyncCallback userCallback, Object stateObject);

        /// <summary>
        /// Waits for the pending asynchronous weather conditions retrieval to complete.
        /// </summary>
        /// <param name="result">The reference to the pending asynchronous request to finish.</param>
        /// <returns>Current weather conditions</returns>
        CurrentWeatherInfo EndGetCurrentConditions(IAsyncResult result);

        /// <summary>
        /// Retrieves Weather forecast for today and (days-1) days
        /// </summary>
        /// <param name="location">location</param>
        /// <param name="days">number of days in the forecast, maximum is 5</param>
        /// <returns>Weather forecast in the XML format</returns>
        string GetWeatherForecastAsXml(Location location, int days);

        /// <summary>
        /// Retrieves Weather forecast for today and (days-1) days
        /// </summary>
        /// <param name="zipCode">US 5-digit zip code</param>
        /// <param name="days">number of days in the forecast, maximum is 5</param>
        /// <returns>Weather forecast in the XML format</returns>
        string GetWeatherForecastAsXml(USZipCode zipCode, int days);

        /// <summary>
        /// Retrieves Weather forecast for today and (days-1) days
        /// </summary>
        /// <param name="location">location</param>
        /// <param name="days">number of days in the forecast, maximum is 5</param>
        /// <returns>Weather forceast</returns>
        ForecastWeatherInfo GetWeatherForecast(Location location, int days);

        /// <summary>
        /// Retrieves Weather forecast for today and (days-1) days
        /// </summary>
        /// <param name="zipCode">US 5-digit zip code</param>
        /// <param name="days">number of days in the forecast, maximum is 5</param>
        /// <returns>Weather forecast</returns>
        ForecastWeatherInfo GetWeatherForecast(USZipCode zipCode, int days);

        /// <summary>
        /// Begins an asynchronous weather forecast retrieval operation.
        /// </summary>
        /// <param name="location">location</param>
        /// <param name="days">number of days in the forecast, maximum is 5</param>
        /// <param name="userCallback">An optional asynchronous callback, to be called when the weather forecast retrieval is complete.</param>
        /// <param name="stateObject">A user-provided object that distinguishes this particular asynchronous weather forecast retrieval request from other requests.</param>
        /// <returns>An IAsyncResult that represents the asynchronous weather forecast retrieval, which could still be pending.</returns>
        IAsyncResult BeginGetWeatherForecast(Location location, int days, AsyncCallback userCallback, Object stateObject);

        /// <summary>
        /// Begins an asynchronous weather forecast retrieval operation.
        /// </summary>
        /// <param name="zipCode">US 5-digit zip code</param>
        /// <param name="days">number of days in the forecast, maximum is 5</param>
        /// <param name="userCallback">An optional asynchronous callback, to be called when the weather forecast retrieval is complete.</param>
        /// <param name="stateObject">A user-provided object that distinguishes this particular asynchronous weather forecast retrieval request from other requests.</param>
        /// <returns>An IAsyncResult that represents the asynchronous weather forecast retrieval, which could still be pending.</returns>
        IAsyncResult BeginGetWeatherForecast(USZipCode zipCode, int days, AsyncCallback userCallback, Object stateObject);

        /// <summary>
        /// Waits for the pending asynchronous weather forecast retrieval to complete.
        /// </summary>
        /// <param name="result">The reference to the pending asynchronous request to finish.</param>
        /// <returns>Weather forecast</returns>
        ForecastWeatherInfo EndGetWeatherForecast(IAsyncResult result);
    }
}